/*
 * Copyright 2011 Angel Sanadinov
 *
 * This file is part of VBox WMI.
 *
 * VBox WMI is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * VBox WMI is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with VBox WMI.  If not, see <http://www.gnu.org/licenses/>.
 */

package Managers;

import java.sql.Driver;
import java.sql.ResultSet;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import Beans.LogBean;
import Beans.UserBean;
import Beans.ServerBean;
import Beans.PermissionsBean;
import Beans.VirtualResourceBean;
import Beans.InternalNetworkBean;
import java.util.EnumMap;
import java.util.ArrayList;
import Utilities.Constants;
import Utilities.Interfaces.Controllable;
import Utilities.Interfaces.SelfValidating;
import Utilities.Constants.VirtualResourceType;
import Managers.Utilities.DatabaseManipulationResult;
import Utilities.ConfigurationReader;

/**
 * Manager for the database operations.
 *
 * @see DatabaseManager#DatabaseManager(java.lang.String, java.lang.String,
 * java.lang.String, java.lang.String, Managers.LogsManager) Constructor
 *
 * @author Angel Sanadinov
 */
public class DatabaseManager implements SelfValidating, Controllable
{

    //<editor-fold defaultstate="collapsed" desc="Table names and columns definitons">
    //-------------------------------_Table = Name
    private static final String TABLE_LOGS = "logs";
    private static final String TABLE_PERMISSIONS = "permissions";
    private static final String TABLE_SERVERS = "servers";
    private static final String TABLE_USERS = "users";
    private static final String TABLE_V_RESOURCES = "virtual_resources";
    private static final String TABLE_INTERNAL_NETWORKS = "internal_networks";
    private static final String TABLE_TEMP_COUNT_COLUMN = "count_column";

    //------------------------- Table_Column = Label
    private static final String LOGS_USER_ID = "user_id";
    private static final String LOGS_SERVER_ID = "server_id";
    private static final String LOGS_EVENT_ID = "event_id";
    private static final String LOGS_EVENT_DATE = "event_date";
    private static final String LOGS_SEVERITY = "severity";
    private static final String LOGS_DESCRIPTION = "description";

    //------------------------- Table_______Column = Label
    private static final String PERMISSIONS_USER_ID = "user_id";
    private static final String PERMISSIONS_SERVER_ID = "server_id";
    private static final String PERMISSIONS_MACHINES_PERM = "virtual_machines_permissions";
    private static final String PERMISSIONS_MEDIA_PERM = "virtual_media_permissions";
    private static final String PERMISSIONS_NETWORKS_PERM = "virtual_networks_permissions";

    //------------------------- Table___Column = Label
    private static final String SERVERS_SERVER_ID = "server_id";
    private static final String SERVERS_DATE_ADDED = "date_added";
    private static final String SERVERS_NAME = "name";
    private static final String SERVERS_DESCRIPTION = "description";
    private static final String SERVERS_ADDRESS = "address";
    private static final String SERVERS_WS_USER = "webservice_user";
    private static final String SERVERS_WS_PASSWORD = "webservice_password";
    private static final String SERVERS_SF_ROOT = "shared_folders_root";
    private static final String SERVERS_VRDP_PORTS_LOW = "vrdpPortsRangeLow";
    private static final String SERVERS_VRDP_PORTS_HIGH = "vrdpPortsRangeHigh";
    private static final String SERVERS_VRDP_PORT_PER_VM = "vrdpPortsPerMachine";
    private static final String SERVERS_VRDP_ALLOCATED_SLOTS = "vrdpAllocatedSlots";

    //------------------------- Table_Column = Label
    private static final String USERS_ID = "user_id";
    private static final String USERS_NAME = "username";
    private static final String USERS_PASSWORD = "password";
    private static final String USERS_DATE_CREATED = "date_created";
    private static final String USERS_DATE_LAST_LOGIN = "date_last_login";
    private static final String USERS_ACCOUNT_LEVEL = "account_level";
    private static final String USERS_LAST_lOGIN_IP = "last_login_address";

    //------------------------- Table______Column = Label
    private static final String V_RESOURCES_RESOURCE_ID = "resource_id";
    private static final String V_RESOURCES_SERVER_ID = "server_id";
    private static final String V_RESOURCES_OWNER_ID = "owner_id";
    private static final String V_RESOURCES_DATE_CREATED = "date_created";
    private static final String V_RESOURCES_PERMISSIONS = "permissions";
    private static final String V_RESOURCES_RESOURCE_TYPE = "resource_type";

    //------------------------- Table_____________Column = Label
    private static final String INTERNAL_NETWORKS_NETWORK_ID = "network_id";
    private static final String INTERNAL_NETWORKS_SERVER_ID = "server_id";
    private static final String INTERNAL_NETWORKS_EXTERNAL_NAME = "network_name";
    private static final String INTERNAL_NETWORKS_DHCP_AVAILABLE = "dhcp_available";
    private static final String INTERNAL_NETWORKS_NUMBER_OF_ATTACHED_NICS = "attached_nics_number";
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc="Prepared statements names">
    /** Prepared statement names enumeration. */
    private enum StatementNames
    {
        //Logs
        LOGS_INSERT, 
        LOGS_GET_ALL, LOGS_GET_BY_EVENT_ID, LOGS_GET_BY_SEVERITY, LOGS_GET_BY_INITIATOR_ID,
        LOGS_GET_BY_SERVER_ID,

        //Permissions
        PERMISSIONS_INSERT, PERMISSIONS_UPDATE, PERMISSIONS_REMOVE,
        PERMISSIONS_GET_BY_USER_ID, PERMISSIONS_GET_BY_SERVER_ID, 
        PERMISSIONS_GET_FOR_USER_ON_SERVER, PERMISSIONS_REMOVE_ALL_FOR_USER,
        PERMISSIONS_GET_NUMBER_FOR_USER,

        //Servers
        SERVERS_GET_BY_ID, SERVERS_GET_BY_ADDRESS, SERVERS_GET_ALL, SERVERS_GET_CREDENTIALS,
        SERVERS_GET_SHARED_FOLDERS_ROOT, SERVERS_UPDATE_VRDP_SLOTS,
        SERVERS_INSERT, SERVERS_UPDATE, SERVERS_REMOVE,

        //Users
        USERS_GET_BY_ID, USERS_GET_BY_NAME, USERS_GET_ALL,
        USERS_INSERT, USERS_REMOVE, USERS_UPDATE_LAST_LOGIN,
        USERS_UPDATE_ACCOUNT_LEVEL, USERS_RESET_PASSWORD,
        USERS_VERIFY_CREDENTIALS,

        //Virtual Resources
        RESOURCES_GET_BY_ID, RESOURCES_GET_ALL_BY_SERVER, RESOURCES_GET_ALL_BY_OWNER, RESOURCES_GET_ALL,
        RESOURCES_INSERT, RESOURCES_REMOVE, RESOURCES_UPDATE_OWNER, RESOURCES_UPDATE_PERMISSIONS,
        RESOURCES_GET_NUMBER_FOR_USER,

        //Internal Networks
        INTERNAL_NET_GET_BY_ID, INTERNAL_NET_GET_ALL, INTERNAL_NET_GET_ALL_BY_SERVER,
        INTERNAL_NET_INSERT, INTERNAL_NET_REMOVE, INTERNAL_NET_CHANGE_NAME,
        INTERNAL_NET_UPDATE_DHCP_AVAIL, INTERNAL_NET_UPDATE_NICS, INTERNAL_NET_GET_NICS
    }
    //</editor-fold>

    private Driver databaseDriver;          //database driver
    private Connection databaseConnection;  //the database connection
    private LogsManager logsManager;        //reference to the logs manager
    private EnumMap<StatementNames, PreparedStatement> preparedStatements; //list of prepared sql statements
    private boolean isValid = false;        //manager validity
    private String databaseURL;             //database URL
    private String databaseUsername;        //database username
    private String databasePassword;        //database password
    private boolean connectionVerificationEnabled; //is connection verification enabled

    /**
     * Constructs the manager object.
     *
     * @param logger reference to the logs manager
     * @param configuration configuration parameters for the manager
     *
     * @see DriverManager#getConnection(java.lang.String) URL Info
     */
    public DatabaseManager(LogsManager logger, ConfigurationReader configuration)
    {
        this.logsManager = logger; //retrieves the logs manager reference

        try
        {
            String paramDatabaseDriver = configuration.getParameter(ConfigurationReader.PARAM_DATABASE_DRIVER);
            String paramDatabaseURL = "jdbc:" + configuration.getParameter(ConfigurationReader.PARAM_DATABASE_SUBPROTOCOL)
                                    + "://" + configuration.getParameter(ConfigurationReader.PARAM_DATABASE_ADDRESS)
                                    + ":" + configuration.getParameter(ConfigurationReader.PARAM_DATABASE_PORT)
                                    + "/" +configuration.getParameter(ConfigurationReader.PARAM_DATABASE_NAME);
            String paramDatabaseUsername = configuration.getParameter(ConfigurationReader.PARAM_DATABASE_USER);
            String paramDatabasePassword = configuration.getParameter(ConfigurationReader.PARAM_DATABASE_PASSWORD);


            //instantiates the database driver
            Class.forName(paramDatabaseDriver).newInstance();

            //establishes the database connection
            this.databaseConnection = DriverManager.getConnection(paramDatabaseURL, paramDatabaseUsername, paramDatabasePassword);
            this.databaseDriver = DriverManager.getDriver(paramDatabaseURL);
            logsManager.logSystemEvent(System.currentTimeMillis(), 
                                        Constants.LOG_SEVERITY_INFORMATION,
                                        "Database Manager started");

            //attempts to build the prepared statements map
            if(prepareStatements())
                isValid = true; //the manager is valid if the map was built
            else
                ;

            this.databaseURL = paramDatabaseURL;
            this.databaseUsername = paramDatabaseUsername;
            this.databasePassword = paramDatabasePassword;

            connectionVerificationEnabled = true;
            try
            {
                connectionVerificationEnabled = Boolean.parseBoolean(configuration.getParameter(
                        ConfigurationReader.PARAM_ALWAYS_VERIFY_DATABASE_CONNECTION));
            }
            catch(Exception e)
            {
                logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_WARNING,
                                           "Database manager: Failed to parse initialization parameter."
                                           + " Default value (" + connectionVerificationEnabled
                                           + ") for connectionVerificationEnabled will be used.");
            }
        }
        catch(Exception e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_ERROR, e.getMessage());
            isValid = false;
        }
    }

    /**
     * Builds prepared SQL statements for most of the database operations.<br><br>
     *
     * <b>Note:</b> <i>Prepared statements are not built for the virtual resource
     * management operations.</i>
     *
     * @return <code>true</code> if the map was successfully built or <code>false</code>
     *         otherwise
     *
     * @see PreparedStatement Prepared Statement
     */
    private boolean prepareStatements()
    {
        //number of entries in the map; !!! Update when adding/removing entries
        int numberOfPreparedStatements = 50;
        //the prepared statements map is initialized
        preparedStatements = new EnumMap<StatementNames, PreparedStatement>(StatementNames.class);
        //array of statement names, each statement must have a unique name
        StatementNames[] statementNames = new StatementNames[numberOfPreparedStatements];
        //the corresponding SQL statements
        String[] statementSQL = new String[numberOfPreparedStatements];
        
        int statementIndex = 0;

        //<editor-fold defaultstate="collapsed" desc="Prepared Statements Initialization Data">
        //Prepared statements for logs management
        statementSQL[statementIndex] = "SELECT * FROM " + TABLE_LOGS + " WHERE " + LOGS_EVENT_ID + " = ? LIMIT 1;";
        statementNames[statementIndex] = StatementNames.LOGS_GET_BY_EVENT_ID;
        statementIndex++;

        statementSQL[statementIndex] = "SELECT * FROM " + TABLE_LOGS
                          + " ORDER BY " + LOGS_EVENT_DATE + " DESC, " + LOGS_EVENT_ID + " DESC;";
        statementNames[statementIndex] = StatementNames.LOGS_GET_ALL;
        statementIndex++;

        statementSQL[statementIndex] = "SELECT * FROM " + TABLE_LOGS + " WHERE " + LOGS_USER_ID
                          + " = ? ORDER BY " + LOGS_EVENT_DATE + " DESC, " + LOGS_EVENT_ID + " DESC;";
        statementNames[statementIndex] = StatementNames.LOGS_GET_BY_INITIATOR_ID;
        statementIndex++;

        statementSQL[statementIndex] = "SELECT * FROM " + TABLE_LOGS + " WHERE " + LOGS_SERVER_ID
                          + " = ? ORDER BY " + LOGS_EVENT_DATE + " DESC, " + LOGS_EVENT_ID + " DESC;";
        statementNames[statementIndex] = StatementNames.LOGS_GET_BY_SERVER_ID;
        statementIndex++;

        statementSQL[statementIndex] = "SELECT * FROM " + TABLE_LOGS + " WHERE " + LOGS_SEVERITY
                          + " = ? ORDER BY " + LOGS_EVENT_DATE + " DESC, " + LOGS_EVENT_ID + " DESC;";
        statementNames[statementIndex] = StatementNames.LOGS_GET_BY_SEVERITY;
        statementIndex++;

        statementSQL[statementIndex] = "INSERT INTO " + TABLE_LOGS + " ("
                        + LOGS_USER_ID + ", " + LOGS_SERVER_ID + ", " + LOGS_EVENT_DATE + ", " + LOGS_SEVERITY + ", " + LOGS_DESCRIPTION
                        + ") VALUES (?, ?, ?, ?, ?);";
        statementNames[statementIndex] = StatementNames.LOGS_INSERT;
        statementIndex++;

        //Prepared statements for permissions management
        statementSQL[statementIndex] = "SELECT * FROM " + TABLE_PERMISSIONS + " WHERE "
                            + PERMISSIONS_USER_ID + " = ? AND " + PERMISSIONS_SERVER_ID + " = ? LIMIT 1;";
        statementNames[statementIndex] = StatementNames.PERMISSIONS_GET_FOR_USER_ON_SERVER;
        statementIndex++;

        statementSQL[statementIndex] = "INSERT INTO " + TABLE_PERMISSIONS + " ("
                        + PERMISSIONS_USER_ID + ", " + PERMISSIONS_SERVER_ID + ", "
                        + PERMISSIONS_MACHINES_PERM + ", " + PERMISSIONS_MEDIA_PERM + ", "
                        + PERMISSIONS_NETWORKS_PERM + ") VALUES (?, ?, ?, ?, ?);";
        statementNames[statementIndex] = StatementNames.PERMISSIONS_INSERT;
        statementIndex++;

        statementSQL[statementIndex] = "UPDATE " + TABLE_PERMISSIONS + " SET "
                        + PERMISSIONS_MACHINES_PERM + " = ?, " + PERMISSIONS_MEDIA_PERM + " = ?, "
                        + PERMISSIONS_NETWORKS_PERM + " = ? WHERE "
                        + PERMISSIONS_USER_ID + " = ? AND " + PERMISSIONS_SERVER_ID + " = ? LIMIT 1;";
        statementNames[statementIndex] = StatementNames.PERMISSIONS_UPDATE;
        statementIndex++;

        statementSQL[statementIndex] = "DELETE FROM " + TABLE_PERMISSIONS + " WHERE "
                        + PERMISSIONS_USER_ID + " = ? AND " + PERMISSIONS_SERVER_ID + " = ? LIMIT 1;";
        statementNames[statementIndex] = StatementNames.PERMISSIONS_REMOVE;
        statementIndex++;

        statementSQL[statementIndex] = "DELETE FROM " + TABLE_PERMISSIONS + " WHERE " + PERMISSIONS_USER_ID + " = ?";
        statementNames[statementIndex] = StatementNames.PERMISSIONS_REMOVE_ALL_FOR_USER;
        statementIndex++;

        statementSQL[statementIndex] = "SELECT * FROM " + TABLE_PERMISSIONS + " WHERE " + PERMISSIONS_USER_ID + " = ?;";
        statementNames[statementIndex] = StatementNames.PERMISSIONS_GET_BY_USER_ID;
        statementIndex++;

        statementSQL[statementIndex] = "SELECT * FROM " + TABLE_PERMISSIONS + " WHERE " + PERMISSIONS_SERVER_ID + " = ?;";
        statementNames[statementIndex] = StatementNames.PERMISSIONS_GET_BY_SERVER_ID;
        statementIndex++;

        statementSQL[statementIndex] = "SELECT count(*) AS " + TABLE_TEMP_COUNT_COLUMN + " FROM "
                                       + TABLE_PERMISSIONS + " WHERE " + PERMISSIONS_USER_ID + " = ?;";
        statementNames[statementIndex] = StatementNames.PERMISSIONS_GET_NUMBER_FOR_USER;
        statementIndex++;

        //Prepared statements for servers management
        statementSQL[statementIndex] = "SELECT * FROM " + TABLE_SERVERS + " WHERE " + SERVERS_SERVER_ID + " = ? LIMIT 1;";
        statementNames[statementIndex] = StatementNames.SERVERS_GET_BY_ID;
        statementIndex++;

        statementSQL[statementIndex] = "SELECT * FROM " + TABLE_SERVERS + " WHERE " + SERVERS_ADDRESS + " = ? LIMIT 1;";
        statementNames[statementIndex] = StatementNames.SERVERS_GET_BY_ADDRESS;
        statementIndex++;

        statementSQL[statementIndex] = "SELECT * FROM " + TABLE_SERVERS + ";";
        statementNames[statementIndex] = StatementNames.SERVERS_GET_ALL;
        statementIndex++;

        statementSQL[statementIndex] = "SELECT " + SERVERS_WS_USER + ", " + SERVERS_WS_PASSWORD + " FROM " + TABLE_SERVERS +
                                    " WHERE " + SERVERS_SERVER_ID + " = ? LIMIT 1;";
        statementNames[statementIndex] = StatementNames.SERVERS_GET_CREDENTIALS;
        statementIndex++;

        statementSQL[statementIndex] = "SELECT " + SERVERS_SF_ROOT + " FROM " + TABLE_SERVERS
                           + " WHERE " + SERVERS_SERVER_ID + " = ? LIMIT 1;";
        statementNames[statementIndex] = StatementNames.SERVERS_GET_SHARED_FOLDERS_ROOT;
        statementIndex++;

        statementSQL[statementIndex] = "UPDATE " + TABLE_SERVERS + " SET " + SERVERS_VRDP_ALLOCATED_SLOTS + " = ? "
                                    + "WHERE " + SERVERS_SERVER_ID + " = ? LIMIT 1;";
        statementNames[statementIndex] = StatementNames.SERVERS_UPDATE_VRDP_SLOTS;
        statementIndex++;

        statementSQL[statementIndex] = "INSERT INTO " + TABLE_SERVERS + " ("
                                    + SERVERS_NAME + ", " + SERVERS_DESCRIPTION + ", " + SERVERS_ADDRESS + ", "
                                    + SERVERS_WS_USER + ", " + SERVERS_WS_PASSWORD + "," + SERVERS_SF_ROOT + ","
                                    + SERVERS_VRDP_PORTS_LOW + "," + SERVERS_VRDP_PORTS_HIGH + ","
                                    + SERVERS_VRDP_PORT_PER_VM
                                    + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);";
        statementNames[statementIndex] = StatementNames.SERVERS_INSERT;
        statementIndex++;

        statementSQL[statementIndex] = "UPDATE " + TABLE_SERVERS
                                    + " SET " + SERVERS_NAME + " = ?, " + SERVERS_DESCRIPTION + " = ?, "
                                    + SERVERS_ADDRESS + " = ?, " + SERVERS_WS_USER + " = ?, "
                                    + SERVERS_WS_PASSWORD + " = ?, " + SERVERS_SF_ROOT + " = ?, "
                                    + SERVERS_VRDP_PORTS_LOW + " = ?, " + SERVERS_VRDP_PORTS_HIGH + " = ?, "
                                    + SERVERS_VRDP_PORT_PER_VM
                                    + " = ? WHERE " + SERVERS_SERVER_ID + " = ? LIMIT 1;";
        statementNames[statementIndex] = StatementNames.SERVERS_UPDATE;
        statementIndex++;

        statementSQL[statementIndex] = "DELETE FROM " + TABLE_SERVERS + " WHERE " + SERVERS_SERVER_ID + " = ? LIMIT 1;";
        statementNames[statementIndex] = StatementNames.SERVERS_REMOVE;
        statementIndex++;

        //Prepared statements for users management
        statementSQL[statementIndex] = "SELECT * FROM " + TABLE_USERS + " WHERE " + USERS_ID + " = ? LIMIT 1;";
        statementNames[statementIndex] = StatementNames.USERS_GET_BY_ID;
        statementIndex++;

        statementSQL[statementIndex] = "SELECT * FROM " + TABLE_USERS + " WHERE " + USERS_NAME + " = ? LIMIT 1;";
        statementNames[statementIndex] = StatementNames.USERS_GET_BY_NAME;
        statementIndex++;

        statementSQL[statementIndex] = "SELECT * FROM " + TABLE_USERS + ";";
        statementNames[statementIndex] = StatementNames.USERS_GET_ALL;
        statementIndex++;

        statementSQL[statementIndex] = "INSERT INTO " + TABLE_USERS + " (" + USERS_NAME + ", " + USERS_PASSWORD + ", " + USERS_ACCOUNT_LEVEL
                                    + ") VALUES (?, ?, ?);";
        statementNames[statementIndex] = StatementNames.USERS_INSERT;
        statementIndex++;

        statementSQL[statementIndex] = "DELETE FROM " + TABLE_USERS + " WHERE " + USERS_ID + " = ? LIMIT 1;";
        statementNames[statementIndex] = StatementNames.USERS_REMOVE;
        statementIndex++;

        statementSQL[statementIndex] = "UPDATE " + TABLE_USERS 
                                       + " SET " + USERS_DATE_LAST_LOGIN + " = CURRENT_TIMESTAMP, "
                                       + USERS_LAST_lOGIN_IP + " = ? "
                                       + "WHERE " + USERS_ID + " = ? LIMIT 1;";
        statementNames[statementIndex] = StatementNames.USERS_UPDATE_LAST_LOGIN;
        statementIndex++;

        statementSQL[statementIndex] = "SELECT " + USERS_ID + " FROM " + TABLE_USERS
                                    + " WHERE " + USERS_NAME + " = ? AND " + USERS_PASSWORD + " = ? LIMIT 1;";
        statementNames[statementIndex] = StatementNames.USERS_VERIFY_CREDENTIALS;
        statementIndex++;

        statementSQL[statementIndex] = "UPDATE " + TABLE_USERS + " SET " + USERS_ACCOUNT_LEVEL + " = ? WHERE " + USERS_ID + " = ? LIMIT 1;";
        statementNames[statementIndex] = StatementNames.USERS_UPDATE_ACCOUNT_LEVEL;
        statementIndex++;

        statementSQL[statementIndex] = "UPDATE " + TABLE_USERS + " SET " + USERS_PASSWORD + " = ? WHERE " + USERS_ID + " = ? LIMIT 1;";
        statementNames[statementIndex] = StatementNames.USERS_RESET_PASSWORD;
        statementIndex++;

        //Prepared statements for resources management
        statementSQL[statementIndex] = "SELECT * FROM " + TABLE_V_RESOURCES + " WHERE " + V_RESOURCES_RESOURCE_ID + " = ? "
                           + "AND " + V_RESOURCES_SERVER_ID + " = ? "
                           + "AND " + V_RESOURCES_RESOURCE_TYPE + " = ? LIMIT 1;";
        statementNames[statementIndex] = StatementNames.RESOURCES_GET_BY_ID;
        statementIndex++;

        statementSQL[statementIndex] = "SELECT * FROM " + TABLE_V_RESOURCES + " WHERE " + V_RESOURCES_SERVER_ID + " = ?"
                            + " AND " + V_RESOURCES_RESOURCE_TYPE + " = ? ;";
        statementNames[statementIndex] = StatementNames.RESOURCES_GET_ALL_BY_SERVER;
        statementIndex++;

        statementSQL[statementIndex] = "SELECT * FROM " + TABLE_V_RESOURCES + " WHERE " + V_RESOURCES_OWNER_ID + " = ? "
                           + "AND " + V_RESOURCES_RESOURCE_TYPE + " = ? ;";
        statementNames[statementIndex] = StatementNames.RESOURCES_GET_ALL_BY_OWNER;
        statementIndex++;

        statementSQL[statementIndex] = "SELECT * FROM " + TABLE_V_RESOURCES + " WHERE " + V_RESOURCES_RESOURCE_TYPE + " = ? ;";
        statementNames[statementIndex] = StatementNames.RESOURCES_GET_ALL;
        statementIndex++;

        statementSQL[statementIndex] = "SELECT count(*) AS " + TABLE_TEMP_COUNT_COLUMN + " FROM "
                            + TABLE_V_RESOURCES + " WHERE " + V_RESOURCES_OWNER_ID + " = ?"
                            + " AND " + V_RESOURCES_RESOURCE_TYPE + " = ? ;";
        statementNames[statementIndex] = StatementNames.RESOURCES_GET_NUMBER_FOR_USER;
        statementIndex++;

        statementSQL[statementIndex] = "INSERT INTO " + TABLE_V_RESOURCES + " ("
                            + V_RESOURCES_RESOURCE_ID + ", " + V_RESOURCES_SERVER_ID + ", " + V_RESOURCES_OWNER_ID
                            + ", " + V_RESOURCES_PERMISSIONS + ", " + V_RESOURCES_RESOURCE_TYPE
                            + ") VALUES (?, ?, ?, ?, ?);";
        statementNames[statementIndex] = StatementNames.RESOURCES_INSERT;
        statementIndex++;

        statementSQL[statementIndex] = "DELETE FROM " + TABLE_V_RESOURCES + " WHERE " + V_RESOURCES_RESOURCE_ID + " = ? "
                           + "AND " + V_RESOURCES_SERVER_ID + " = ? LIMIT 1;";
        statementNames[statementIndex] = StatementNames.RESOURCES_REMOVE;
        statementIndex++;

        statementSQL[statementIndex] = "UPDATE " + TABLE_V_RESOURCES + " SET " + V_RESOURCES_OWNER_ID + " = ? "
                           + "WHERE " + V_RESOURCES_RESOURCE_ID + " = ? " + "AND " + V_RESOURCES_SERVER_ID + " = ? LIMIT 1;";
        statementNames[statementIndex] = StatementNames.RESOURCES_UPDATE_OWNER;
        statementIndex++;

        statementSQL[statementIndex] = "UPDATE " + TABLE_V_RESOURCES + " SET " + V_RESOURCES_PERMISSIONS + " = ? "
                           + "WHERE " + V_RESOURCES_RESOURCE_ID + " = ? AND " + V_RESOURCES_SERVER_ID + " = ? LIMIT 1;";
        statementNames[statementIndex] = StatementNames.RESOURCES_UPDATE_PERMISSIONS;
        statementIndex++;

        //Prepared statements for internal networks management
        statementSQL[statementIndex] = "SELECT * FROM " + TABLE_INTERNAL_NETWORKS + " WHERE " + INTERNAL_NETWORKS_NETWORK_ID + " = ? "
                           + "AND " + INTERNAL_NETWORKS_SERVER_ID + " = ? LIMIT 1;";
        statementNames[statementIndex] = StatementNames.INTERNAL_NET_GET_BY_ID;
        statementIndex++;

        statementSQL[statementIndex] = "SELECT * FROM " + TABLE_INTERNAL_NETWORKS + ";";
        statementNames[statementIndex] = StatementNames.INTERNAL_NET_GET_ALL;
        statementIndex++;

        statementSQL[statementIndex] = "SELECT * FROM " + TABLE_INTERNAL_NETWORKS + " WHERE " + INTERNAL_NETWORKS_SERVER_ID + " = ? ;";
        statementNames[statementIndex] = StatementNames.INTERNAL_NET_GET_ALL_BY_SERVER;
        statementIndex++;

        statementSQL[statementIndex] = "INSERT INTO " + TABLE_INTERNAL_NETWORKS + " ("
                           + INTERNAL_NETWORKS_NETWORK_ID + ", " + INTERNAL_NETWORKS_SERVER_ID
                           + ", " + INTERNAL_NETWORKS_EXTERNAL_NAME
                           + ") VALUES (?, ?, ?);";
        statementNames[statementIndex] = StatementNames.INTERNAL_NET_INSERT;
        statementIndex++;

        statementSQL[statementIndex] = "DELETE FROM " + TABLE_INTERNAL_NETWORKS + " WHERE " + INTERNAL_NETWORKS_NETWORK_ID + " = ? "
                           + "AND " + INTERNAL_NETWORKS_SERVER_ID + " = ? LIMIT 1;";
        statementNames[statementIndex] = StatementNames.INTERNAL_NET_REMOVE;
        statementIndex++;

        statementSQL[statementIndex] = "UPDATE " + TABLE_INTERNAL_NETWORKS + " SET " + INTERNAL_NETWORKS_EXTERNAL_NAME + " = ? "
                           + "WHERE " + INTERNAL_NETWORKS_NETWORK_ID + " = ? AND " + INTERNAL_NETWORKS_SERVER_ID + " = ? LIMIT 1;";
        statementNames[statementIndex] = StatementNames.INTERNAL_NET_CHANGE_NAME;
        statementIndex++;

        statementSQL[statementIndex] = "UPDATE " + TABLE_INTERNAL_NETWORKS + " SET " + INTERNAL_NETWORKS_DHCP_AVAILABLE + " = ? "
                           + "WHERE " + INTERNAL_NETWORKS_NETWORK_ID + " = ? AND " + INTERNAL_NETWORKS_SERVER_ID + " = ? LIMIT 1;";
        statementNames[statementIndex] = StatementNames.INTERNAL_NET_UPDATE_DHCP_AVAIL;
        statementIndex++;

        statementSQL[statementIndex] = "UPDATE " + TABLE_INTERNAL_NETWORKS + " SET " + INTERNAL_NETWORKS_NUMBER_OF_ATTACHED_NICS + " = ? "
                           + "WHERE " + INTERNAL_NETWORKS_NETWORK_ID + " = ? AND " + INTERNAL_NETWORKS_SERVER_ID + " = ? LIMIT 1;";
        statementNames[statementIndex] = StatementNames.INTERNAL_NET_UPDATE_NICS;
        statementIndex++;

        statementSQL[statementIndex] = "SELECT " + INTERNAL_NETWORKS_NUMBER_OF_ATTACHED_NICS + " FROM " + TABLE_INTERNAL_NETWORKS
                           + " WHERE " + INTERNAL_NETWORKS_NETWORK_ID + " = ? AND " + INTERNAL_NETWORKS_SERVER_ID + " = ? LIMIT 1;";
        statementNames[statementIndex] = StatementNames.INTERNAL_NET_GET_NICS;
        statementIndex++;
        //</editor-fold>

        try
        {
            //builds the map using the supplied names and sql statements
            for(int i = 0; i < numberOfPreparedStatements; i++)
                preparedStatements.put(statementNames[i], databaseConnection.prepareStatement(statementSQL[i]));
            
            return true;
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_ERROR, 
                                       "Preparing Statements: " + e.getMessage());
            return false;
        }
    }

    /**
     * Stops the manager and removes any associated resource references.
     */
    @Override
    public void stop()
    {
        logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_INFORMATION, "Database manager stopping...");

        databaseURL = null;
        databaseUsername = null;
        databasePassword = null;

        try
        {
            //attempts to close the database connection
            databaseConnection.close();
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_ERROR, e.getMessage());
        }
        finally
        {
            databaseConnection = null;
            
            for(PreparedStatement satement : preparedStatements.values())
            {
                try
                {
                    satement.close();
                }
                catch(SQLException e)
                {
                    logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_ERROR, e.getMessage());
                }
            }
            preparedStatements.clear();
            preparedStatements = null;
            
            try
            {
                DriverManager.deregisterDriver(databaseDriver);
            }
            catch(SQLException e)
            {
                logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_ERROR, e.getMessage());
            }

            databaseDriver = null;
            
            logsManager = null;
        }
    }

    /**
     * Checks the validity of the manager. <br><br>
     *
     * The manager is valid only after all of its components have been initialized.
     *
     * @return <code>true</code> if the manager is valid
     */
    @Override
    public boolean isValid()
    {
        return isValid;
    }

    /**
     * Verifies the database connection and re-establishes if necessary.
     */
    private void verifyConnection()
    {
        try
        {
            //checks if the connection is invalid
            if(!databaseConnection.isValid(0))
            {
                //attempts to reconnect
                databaseConnection = DriverManager.getConnection(databaseURL,
                                                                 databaseUsername,
                                                                 databasePassword);
                //rebuilds the prepared statements
                prepareStatements();
            }
            else
                ;
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), 
                                       Constants.LOG_SEVERITY_ERROR,
                                       e.getMessage());
        }
    }

    //<editor-fold defaultstate="collapsed" desc="Logs management methods">
    /**
     * Retrieves a log from the database based on the supplied event id.
     *
     * @param eventId the id of the log to be retrieved
     * @return the log data if it is available or <code>null</code> otherwise
     */
    public LogBean getLog(int eventId)
    {
        LogBean log = null;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //retrieves the prepared sql statement and executes it using the supplied event id
            PreparedStatement statement = preparedStatements.get(StatementNames.LOGS_GET_BY_EVENT_ID);
            statement.setInt(1, eventId);
            ResultSet result = statement.executeQuery(); //result from the query

            if(result.next()) //checks if there is available data
            {
                //constructs the log object
                log = new LogBean(result.getInt(LOGS_USER_ID),
                                  result.getInt(LOGS_SERVER_ID),
                                  result.getInt(LOGS_EVENT_ID),
                                  result.getString(LOGS_SEVERITY),
                                  result.getTimestamp(LOGS_EVENT_DATE),
                                  result.getString(LOGS_DESCRIPTION));
            }
            else
                log = null;
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            log = null;
        }
        finally
        {
            return log;
        }
    }

    /**
     * Retrieves all logs from the database.
     *
     * @return a list with all the available logs or an empty list if there is no
     *         data
     */
    public ArrayList<LogBean> getLogs()
    {
        ArrayList<LogBean> logs = new ArrayList<LogBean>();

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //executes the prepared statement and retrieves the result
            ResultSet result = preparedStatements.get(StatementNames.LOGS_GET_ALL).executeQuery();
            //fills the output logs list using the retrieved data from the query
            fillLogsList(result, logs);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
        }
        finally
        {
            return logs;
        }
    }

    /**
     * Retrieves all logs from the database that are associated with the supplied
     * initiator id.
     *
     * @param initiatorId the id of the user whose logs are to be retrieved
     * @return a list with all the available logs or an empty list if there is no
     *         data
     */
    public ArrayList<LogBean> getLogsByInitiatorId(int initiatorId)
    {
        ArrayList<LogBean> logs = new ArrayList<LogBean>();

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //retrieves and executes the prepared statement
            PreparedStatement statement = preparedStatements.get(StatementNames.LOGS_GET_BY_INITIATOR_ID);
            statement.setInt(1, initiatorId);
            ResultSet result = statement.executeQuery(); //retrieves the result
            fillLogsList(result, logs); //fills the output logs list with the result data
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
        }
        finally
        {
            return logs;
        }
    }

    /**
     * Retrieves all logs from the database that are associated with the supplied
     * server id.
     *
     * @param serverId the id of the server on which the event took place
     * @return a list with all the available logs or an empty list if there is no
     *         data
     */
    public ArrayList<LogBean> getLogsByServerId(int serverId)
    {
        ArrayList<LogBean> logs = new ArrayList<LogBean>();

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //retrieves and executes the prepared statement
            PreparedStatement statement = preparedStatements.get(StatementNames.LOGS_GET_BY_SERVER_ID);
            statement.setInt(1, serverId);
            ResultSet result = statement.executeQuery(); //retrieves the result
            fillLogsList(result, logs); //fills the output logs list with the result data
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
        }
        finally
        {
            return logs;
        }
    }

    /**
     * Retrieves all logs from the database that have the specified severity.
     *
     * @param severity level of logs severity
     * @return a list with all the available logs or an empty list if there is no
     *         data
     *
     * @see Constants Severity Constants
     */
    public ArrayList<LogBean> getLogsBySeverity(String severity)
    {
        ArrayList<LogBean> logs = new ArrayList<LogBean>();

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //retrieves and executes the prepared statement
            PreparedStatement statement = preparedStatements.get(StatementNames.LOGS_GET_BY_SEVERITY);
            statement.setString(1, severity);
            ResultSet result = statement.executeQuery(); //retrieves the result
            fillLogsList(result, logs); //fills the output logs list with the result data
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
        }
        finally
        {
            return logs;
        }
    }

    /**
     * Inserts a new log in the database.
     *
     * @param log data for the new log
     */
    public void insertLog(LogBean log)
    {
        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //retrieves, sets up and executes the proper prepared statement
            PreparedStatement statement = preparedStatements.get(StatementNames.LOGS_INSERT);
            statement.setInt(1, log.getInitiatorId());
            statement.setInt(2, log.getServerId());
            statement.setTimestamp(3, log.getEventDate());
            statement.setString(4, log.getSeverity());
            statement.setString(5, log.getDescription());
            statement.executeUpdate();
        }
        catch(SQLException e)
        {
            //logs insertion should not fail
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_ERROR, e.getMessage());
        }
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc="Permissions management methods">

    /**
     * Retrieves permissions for the supplied user on the specified server.
     *
     * @param userId the id of the owner of the permissions
     * @param serverId the id of the server for which the permissions are valid
     *
     * @return permission data if available or <code>null</code> otherwise
     */
    public PermissionsBean getPermissions(int userId, int serverId)
    {
        PermissionsBean permissions = null;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //retrieves, sets up and executes the prepared statement
            PreparedStatement statement = preparedStatements.get(StatementNames.PERMISSIONS_GET_FOR_USER_ON_SERVER);
            statement.setInt(1, userId);
            statement.setInt(2, serverId);
            ResultSet result = statement.executeQuery();
            if(result.next())
            {
                permissions = new PermissionsBean(result.getInt(PERMISSIONS_USER_ID),
                                                    result.getInt(PERMISSIONS_SERVER_ID),
                                                    result.getString(PERMISSIONS_MACHINES_PERM),
                                                    result.getString(PERMISSIONS_MEDIA_PERM),
                                                    result.getString(PERMISSIONS_NETWORKS_PERM));
            }
            else
                permissions = null;
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            permissions = null;
        }
        finally
        {
            return permissions;
        }
    }

    /**
     * Creates new permissions based on the supplied data.
     *
     * @param permissions permissions data
     * @return an object containing the result of the requested operation
     *
     * @see DatabaseManipulationResult Return Info
     * @see Constants Possible SQL Error Codes
     */
    public DatabaseManipulationResult insertPermissions(PermissionsBean permissions)
    {
        DatabaseManipulationResult result = null;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //retrieves, sets up and executes the prepared statement
            PreparedStatement statement = preparedStatements.get(StatementNames.PERMISSIONS_INSERT);
            statement.setInt(1, permissions.getUserId());
            statement.setInt(2, permissions.getServerId());
            statement.setString(3, permissions.getMachinesPermissions());
            statement.setString(4, permissions.getMediaPermissions());
            statement.setString(5, permissions.getNetworksPermissions());
            statement.executeUpdate();
            result = new DatabaseManipulationResult(true);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            result = new DatabaseManipulationResult(false, e);
        }
        finally
        {
            return result;
        }
    }

    /**
     * Updates existing permissions based on the supplied data.
     *
     * @param permissions permissions data
     *
     * @return an object containing the result of the requested operation
     *
     * @see DatabaseManipulationResult Return Info
     * @see Constants Possible SQL Error Codes
     */
    public DatabaseManipulationResult updatePermissions(PermissionsBean permissions)
    {
        DatabaseManipulationResult result = null;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            PreparedStatement statement = preparedStatements.get(StatementNames.PERMISSIONS_UPDATE);
            statement.setString(1, permissions.getMachinesPermissions());
            statement.setString(2, permissions.getMediaPermissions());
            statement.setString(3, permissions.getNetworksPermissions());
            statement.setInt(4, permissions.getUserId());
            statement.setInt(5, permissions.getServerId());

            if(statement.executeUpdate() == 1)
                result = new DatabaseManipulationResult(true);
            else
                result = new DatabaseManipulationResult(false, Constants.SQL_ERROR_NOT_UPDATED);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            result = new DatabaseManipulationResult(false, e);
        }
        finally
        {
            return result;
        }
    }

    /**
     * Removes the permissions for the supplied user on the specified server.
     *
     * @param userId the id of the owner of the permissions
     * @param serverId the id of the server for which the permissions are valid
     *
     * @return an object containing the result of the requested operation
     *
     * @see DatabaseManipulationResult Return Info
     * @see Constants Possible SQL Error Codes
     */
    public DatabaseManipulationResult removePermissions(int userId, int serverId)
    {
        DatabaseManipulationResult result = null;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //retrieves, sets up and executes the prepared statement
            PreparedStatement statement = preparedStatements.get(StatementNames.PERMISSIONS_REMOVE);
            statement.setInt(1, userId);
            statement.setInt(2, serverId);

            if(statement.executeUpdate() == 1)
                result = new DatabaseManipulationResult(true);
            else
                result = new DatabaseManipulationResult(false, Constants.SQL_ERROR_NOT_REMOVED);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            result = new DatabaseManipulationResult(false, e);
        }
        finally
        {
            return result;
        }
    }

    /**
     * Removes all permissions associated with the supplied user.
     *
     * @param userId the id of the owner of the permissions
     *
     * @return an object containing the result of the requested operation
     *
     * @see DatabaseManipulationResult Return Info
     * @see Constants Possible SQL Error Codes
     */
    public DatabaseManipulationResult removeAllUserPermissions(int userId)
    {
        DatabaseManipulationResult result = null;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //retrieves, sets up and executes the prepared statement
            PreparedStatement statement = preparedStatements.get(StatementNames.PERMISSIONS_REMOVE_ALL_FOR_USER);
            statement.setInt(1, userId);

            statement.executeUpdate();
            result = new DatabaseManipulationResult(true);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            result = new DatabaseManipulationResult(false, e);
        }
        finally
        {
            return result;
        }
    }

    /**
     * Retrieves all permissions for the specified user.
     *
     * @param userId the id of the user, whose permissions are to be retrieved
     * @return a list of all available permissions
     */
    public ArrayList<PermissionsBean> getAllPermissionsForUser(int userId)
    {
        ArrayList<PermissionsBean> permissions = new ArrayList<PermissionsBean>();

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //retrieves, sets up and executes the prepared statement; retrieves and builds the result
            PreparedStatement statement = preparedStatements.get(StatementNames.PERMISSIONS_GET_BY_USER_ID);
            statement.setInt(1, userId);
            ResultSet result = statement.executeQuery();
            fillPermissionsList(result, permissions);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
        }
        finally
        {
            return permissions;
        }
    }

    /**
     * Retrieves all permissions associated with the specified server.
     *
     * @param serverId the id of the server
     * @return a list of all available permissions
     */
    public ArrayList<PermissionsBean> getAllPermissionsForServer(int serverId)
    {
        ArrayList<PermissionsBean> permissions = new ArrayList<PermissionsBean>();

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //retrieves, sets up and executes the prepared statement; retrieves and builds the result
            PreparedStatement statement = preparedStatements.get(StatementNames.PERMISSIONS_GET_BY_SERVER_ID);
            statement.setInt(1, serverId);
            ResultSet result = statement.executeQuery();
            fillPermissionsList(result, permissions);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
        }
        finally
        {
            return permissions;
        }
    }

    /**
     * Retrieves the number of servers on which the specified user has permissions.
     *
     * @param userId the ID of the user to be checked
     * @return the number of servers
     */
    public int getNumberOfPermissionsForUser(int userId)
    {
        int number = 0;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //retrieves, sets up and executes the prepared statement; retrieves and builds the result
            PreparedStatement statement = preparedStatements.get(StatementNames.PERMISSIONS_GET_NUMBER_FOR_USER);
            statement.setInt(1, userId);
            ResultSet result = statement.executeQuery();
            if(result.next())
                number = result.getInt(TABLE_TEMP_COUNT_COLUMN);
            else
                number = 0;
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
        }
        finally
        {
            return number;
        }
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc="Servers management methods">
    /**
     * Retrieves a server based on the supplied id.
     *
     * @param serverId the id of the server to be retrieved
     * @return server data if available or <code>null</code> otherwise
     */
    public ServerBean getServer(int serverId)
    {
        ServerBean server = null;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //retrieves, sets up and executes the prepared statement; retrieves and builds the result
            PreparedStatement statement = preparedStatements.get(StatementNames.SERVERS_GET_BY_ID);
            statement.setInt(1, serverId);
            ResultSet result = statement.executeQuery();
            if(result.next())
            {
                server = new ServerBean(result.getInt(SERVERS_SERVER_ID),
                                        result.getTimestamp(SERVERS_DATE_ADDED),
                                        result.getString(SERVERS_NAME),
                                        result.getString(SERVERS_DESCRIPTION),
                                        result.getString(SERVERS_ADDRESS),
                                        null,
                                        null,
                                        result.getString(SERVERS_SF_ROOT),
                                        result.getInt(SERVERS_VRDP_PORTS_LOW),
                                        result.getInt(SERVERS_VRDP_PORTS_HIGH),
                                        result.getInt(SERVERS_VRDP_PORT_PER_VM),
                                        result.getString(SERVERS_VRDP_ALLOCATED_SLOTS));
            }
            else
                server = null;
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            server = null;
        }
        finally
        {
            return server;
        }
    }

    /**
     * Retrieves a server based on the supplied connection URL.
     *
     * @param webServiceAddress the URL of the server to be retrieved
     * @return server data if available or <code>null</code> otherwise
     */
    public ServerBean getServer(String webServiceAddress)
    {
        ServerBean server = null;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //retrieves, sets up and executes the prepared statement; retrieves and builds the result
            PreparedStatement statement = preparedStatements.get(StatementNames.SERVERS_GET_BY_ADDRESS);
            statement.setString(1, webServiceAddress);
            ResultSet result = statement.executeQuery();
            if(result.next())
            {
                server = new ServerBean(result.getInt(SERVERS_SERVER_ID),
                                        result.getTimestamp(SERVERS_DATE_ADDED),
                                        result.getString(SERVERS_NAME),
                                        result.getString(SERVERS_DESCRIPTION),
                                        result.getString(SERVERS_ADDRESS),
                                        null,
                                        null,
                                        result.getString(SERVERS_SF_ROOT),
                                        result.getInt(SERVERS_VRDP_PORTS_LOW),
                                        result.getInt(SERVERS_VRDP_PORTS_HIGH),
                                        result.getInt(SERVERS_VRDP_PORT_PER_VM),
                                        result.getString(SERVERS_VRDP_ALLOCATED_SLOTS));
            }
            else
                server = null;
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            server = null;
        }
        finally
        {
            return server;
        }
    }

    /**
     * Retrieves all servers.
     *
     * @return a list of all available servers
     */
    public ArrayList<ServerBean> getServers()
    {
        ArrayList<ServerBean> servers = new ArrayList<ServerBean>();

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //retrieves, sets up and executes the prepared statement; retrieves and builds the result
            PreparedStatement statement = preparedStatements.get(StatementNames.SERVERS_GET_ALL);
            ResultSet result = statement.executeQuery();
            fillServersList(result, servers);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
        }
        finally
        {
            return servers;
        }
    }

    /**
     * Retrieves the credentials for the specified server.
     *
     * @param serverId the id of the server
     * @return the server's username and password as a String array if available
     *         or <code>null</code> otherwise.<br>
     *         <i>element 0</i> is the username, <i>element 1</i> is the password
     */
    public String[] getServerCredentials(int serverId)
    {
        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //retrieves, sets up and executes the prepared statement; retrieves and builds the result
            PreparedStatement statement = preparedStatements.get(StatementNames.SERVERS_GET_CREDENTIALS);
            statement.setInt(1, serverId);
            ResultSet result = statement.executeQuery();
            if(result.next())
            {
                String[] credentials = {result.getString(SERVERS_WS_USER), result.getString(SERVERS_WS_PASSWORD)};
                return credentials;
            }
            else
                return null;
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            return null;
        }
    }

    /**
     * Retrieves the shared folders root directory for the specified server.
     *
     * @param serverId the id of the server
     * @return the server's shared folders root directory if available or
     *         <code>null</code> otherwise.
     */
    public String getServerSharedFoldersRoot(int serverId)
    {
        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //retrieves, sets up and executes the prepared statement; retrieves and builds the result
            PreparedStatement statement = preparedStatements.get(StatementNames.SERVERS_GET_SHARED_FOLDERS_ROOT);
            statement.setInt(1, serverId);
            ResultSet result = statement.executeQuery();
            if(result.next())
                return result.getString(SERVERS_SF_ROOT);
            else
                return null;
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            return null;
        }
    }

    /**
     * Updates the allocated VRDP slots list of the specified server.
     *
     * @param serverId the id of the server
     * @param allocatedSlots the new allocated slots list
     * @return an object containing the result of the requested operation
     *
     * @see DatabaseManipulationResult Return Info
     * @see Constants Possible SQL Error Codes
     */
    public DatabaseManipulationResult updateServerVRDPAllocationSlots(int serverId, String allocatedSlots)
    {
        DatabaseManipulationResult result = null;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //retrieves, sets up and executes the prepared statement
            PreparedStatement statement = preparedStatements.get(StatementNames.SERVERS_UPDATE_VRDP_SLOTS);
            statement.setString(1, allocatedSlots);
            statement.setInt(2, serverId);

            if(statement.executeUpdate() == 1)
                result = new DatabaseManipulationResult(true);
            else
                result = new DatabaseManipulationResult(false, Constants.SQL_ERROR_NOT_UPDATED);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            result = new DatabaseManipulationResult(false, e);
        }
        finally
        {
            return result;
        }
    }

    /**
     * Creates a new server in the database, based on the supplied data.
     *
     * @param server server data
     * @return an object containing the result of the requested operation
     *
     * @see DatabaseManipulationResult Return Info
     * @see Constants Possible SQL Error Codes
     */
    public DatabaseManipulationResult insertServer(ServerBean server)
    {
        DatabaseManipulationResult result = null;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //retrieves, sets up and executes the prepared statement
            PreparedStatement statement = preparedStatements.get(StatementNames.SERVERS_INSERT);
            statement.setString(1, server.getName());
            statement.setString(2, server.getDescription());
            statement.setString(3, server.getWebServiceAddress());
            statement.setString(4, server.getWebServiceUser());
            statement.setString(5, server.getWebServicePassword());
            statement.setString(6, server.getSharedFoldersRoot());
            statement.setInt(7, server.getVrdpPortsRangeLow());
            statement.setInt(8, server.getVrdpPortsRangeHigh());
            statement.setInt(9, server.getVrdpPortsPerMachine());
            statement.executeUpdate();
            result = new DatabaseManipulationResult(true);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            result = new DatabaseManipulationResult(false, e);
        }
        finally
        {
            return result;
        }
    }

    /**
     * Updates an existing server, based on the supplied data.
     *
     * @param server server data
     * @return an object containing the result of the requested operation
     *
     * @see DatabaseManipulationResult Return Info
     * @see Constants Possible SQL Error Codes
     */
    public DatabaseManipulationResult updateServer(ServerBean server)
    {
        DatabaseManipulationResult result = null;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //retrieves, sets up and executes the prepared statement
            PreparedStatement statement = preparedStatements.get(StatementNames.SERVERS_UPDATE);
            statement.setString(1, server.getName());
            statement.setString(2, server.getDescription());
            statement.setString(3, server.getWebServiceAddress());
            statement.setString(4, server.getWebServiceUser());
            statement.setString(5, server.getWebServicePassword());
            statement.setString(6, server.getSharedFoldersRoot());
            statement.setInt(7, server.getVrdpPortsRangeLow());
            statement.setInt(8, server.getVrdpPortsRangeHigh());
            statement.setInt(9, server.getVrdpPortsPerMachine());
            statement.setInt(10, server.getServerId());
            
            if(statement.executeUpdate() == 1)
                result = new DatabaseManipulationResult(true);
            else
                result = new DatabaseManipulationResult(false, Constants.SQL_ERROR_NOT_UPDATED);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            result = new DatabaseManipulationResult(false, e);
        }
        finally
        {
            return result;
        }
    }

    /**
     * Removes the server with the specified id.
     *
     * @param serverId the id of the server to be removed
     * @return an object containing the result of the requested operation
     *
     * @see DatabaseManipulationResult Return Info
     * @see Constants Possible SQL Error Codes
     */
    public DatabaseManipulationResult removeServer(int serverId)
    {
        DatabaseManipulationResult result = null;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //retrieves, sets up and executes the prepared statement
            PreparedStatement statement = preparedStatements.get(StatementNames.SERVERS_REMOVE);
            statement.setInt(1, serverId);
            
            if(statement.executeUpdate() == 1)
                result = new DatabaseManipulationResult(true);
            else
                result = new DatabaseManipulationResult(false, Constants.SQL_ERROR_NOT_REMOVED);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            result = new DatabaseManipulationResult(false, e);
        }
        finally
        {
            return result;
        }
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc="Users management methods">
    /**
     * Retrieves the user with the specified id.
     *
     * @param userId the id of the user to be retrieved
     * @return the user data if available or <code>null</code> otherwise
     */
    public UserBean getUser(int userId)
    {
        UserBean user = null;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //retrieves, sets up and executes the prepared statement; retrieves and builds the result
            PreparedStatement statement = preparedStatements.get(StatementNames.USERS_GET_BY_ID);
            statement.setInt(1, userId);
            ResultSet result = statement.executeQuery();
            if(result.next())
            {
                user = new UserBean(result.getInt(USERS_ID),
                                    result.getString(USERS_NAME),
                                    result.getTimestamp(USERS_DATE_CREATED),
                                    result.getTimestamp(USERS_DATE_LAST_LOGIN),
                                    result.getInt(USERS_ACCOUNT_LEVEL),
                                    result.getString(USERS_LAST_lOGIN_IP));
            }
            else
                user = null;
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            user = null;
        }
        finally
        {
            return user;
        }
    }

    /**
     * Retrieves the user with the specified name.
     *
     * @param username the name of the user to be retrieved
     * @return the user data if available or <code>null</code> otherwise
     */
    public UserBean getUser(String username)
    {
        UserBean user = null;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //retrieves, sets up and executes the prepared statement; retrieves and builds the result
            PreparedStatement statement = preparedStatements.get(StatementNames.USERS_GET_BY_NAME);
            statement.setString(1, username);
            ResultSet result = statement.executeQuery();
            if(result.next())
            {
                user = new UserBean(result.getInt(USERS_ID),
                                    result.getString(USERS_NAME),
                                    result.getTimestamp(USERS_DATE_CREATED),
                                    result.getTimestamp(USERS_DATE_LAST_LOGIN),
                                    result.getInt(USERS_ACCOUNT_LEVEL),
                                    result.getString(USERS_LAST_lOGIN_IP));
            }
            else
                user = null;
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            user = null;
        }
        finally
        {
            return user;
        }
    }

    /**
     * Retrieves all users in the database.
     *
     * @return a list of all available users
     */
    public ArrayList<UserBean> getUsers()
    {
        ArrayList<UserBean> users = new ArrayList<UserBean>();

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //retrieves, sets up and executes the prepared statement; retrieves and builds the result
            PreparedStatement statement = preparedStatements.get(StatementNames.USERS_GET_ALL);
            ResultSet result = statement.executeQuery();
            fillUsersList(result, users);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
        }
        finally
        {
            return users;
        }
    }

    /**
     * Creates a new user based on the supplied data.
     *
     * @param user user data
     * @return an object containing the result of the requested operation
     *
     * @see DatabaseManipulationResult Return Info
     * @see Constants Possible SQL Error Codes
     */
    public DatabaseManipulationResult insertUser(UserBean user)
    {
        DatabaseManipulationResult result = null;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //retrieves, sets up and executes the prepared statement
            PreparedStatement statement = preparedStatements.get(StatementNames.USERS_INSERT);
            statement.setString(1, user.getUsername());
            statement.setString(2, user.getPassword());
            statement.setInt(3, user.getAccountLevel());
            statement.executeUpdate();
            result = new DatabaseManipulationResult(true);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            result = new DatabaseManipulationResult(false, e);
        }
        finally
        {
            return result;
        }
    }

    /**
     * Removes the user with the specified id.
     *
     * @param userId the id of the user to be removed
     * @return an object containing the result of the requested operation
     *
     * @see DatabaseManipulationResult Return Info
     * @see Constants Possible SQL Error Codes
     */
    public DatabaseManipulationResult removeUser(int userId)
    {
        DatabaseManipulationResult result = null;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //retrieves, sets up and executes the prepared statement
            PreparedStatement statement = preparedStatements.get(StatementNames.USERS_REMOVE);
            statement.setInt(1, userId);

            if(statement.executeUpdate() == 1)
                result = new DatabaseManipulationResult(true);
            else
                result = new DatabaseManipulationResult(false, Constants.SQL_ERROR_NOT_REMOVED);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            result = new DatabaseManipulationResult(false, e);
        }
        finally
        {
            return result;
        }
    }

    /**
     * Updates the last login timestamp of the user with the specified id.
     *
     * @param userId the id of the user
     * @param userRemoteAddress the IP address of the user's machine
     * @return an object containing the result of the requested operation
     *
     * @see DatabaseManipulationResult Return Info
     * @see Constants Possible SQL Error Codes
     */
    public DatabaseManipulationResult updateUserLastLogin(int userId, String userRemoteAddress)
    {
        DatabaseManipulationResult result = null;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //retrieves, sets up and executes the prepared statement
            PreparedStatement statement = preparedStatements.get(StatementNames.USERS_UPDATE_LAST_LOGIN);
            statement.setString(1, userRemoteAddress);
            statement.setInt(2, userId);
            
            if(statement.executeUpdate() == 1)
                result = new DatabaseManipulationResult(true);
            else
                result = new DatabaseManipulationResult(false, Constants.SQL_ERROR_NOT_UPDATED);
        }
        catch(SQLException e)
        {
            //last login update should not fail
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_ERROR, e.getMessage());
            result = new DatabaseManipulationResult(false, e);
        }
        finally
        {
            return result;
        }
    }

    /**
     * Verifies that the supplied username and password have a match in the database.
     *
     * @param username the username which is to be verified
     * @param password the associated password
     * @return the id of the user with the matching username and password or
     *         <code>0</code> if a match was not found
     */
    public int verifyUserCredentials(String username, String password)
    {
        int userId = 0;

        verifyConnection(); //makes sure the conneciton is valid

        try
        {
            //retrieves, sets up and executes the prepared statement; retrieves and builds the result
            PreparedStatement statement = preparedStatements.get(StatementNames.USERS_VERIFY_CREDENTIALS);
            statement.setString(1, username);
            statement.setString(2, password);
            ResultSet result = statement.executeQuery();
            if(result.next())
                userId = result.getInt(USERS_ID);
            else
                userId = 0;
        }
        catch(SQLException e)
        {
            //credentials verification should not fail
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_ERROR, e.getMessage());
            userId = 0;
        }
        finally
        {
            return userId;
        }
    }

    /**
     * Sets the account level of the specified user.
     *
     * @param userId the id of the user
     * @param accountLevel the new account level
     * @return an object containing the result of the requested operation
     *
     * @see DatabaseManipulationResult Return Info
     * @see Constants Possible SQL Error Codes
     */
    public DatabaseManipulationResult setUserAccountLevel(int userId, int accountLevel)
    {
        DatabaseManipulationResult result = null;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //retrieves, sets up and executes the prepared statement
            PreparedStatement statement = preparedStatements.get(StatementNames.USERS_UPDATE_ACCOUNT_LEVEL);
            statement.setInt(1, accountLevel);
            statement.setInt(2, userId);

            if(statement.executeUpdate() == 1)
                result = new DatabaseManipulationResult(true);
            else
                result = new DatabaseManipulationResult(false, Constants.SQL_ERROR_NOT_UPDATED);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            result = new DatabaseManipulationResult(false, e);
        }
        finally
        {
            return result;
        }
    }

    /**
     * Resets the password of the specified user.
     *
     * @param userId the id of the user
     * @param password the new password for that user
     * @return an object containing the result of the requested operation
     *
     * @see DatabaseManipulationResult Return Info
     * @see Constants Possible SQL Error Codes
     */
    public DatabaseManipulationResult resetUserPassword(int userId, String password)
    {
        DatabaseManipulationResult result = null;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //retrieves, sets up and executes the prepared statement
            PreparedStatement statement = preparedStatements.get(StatementNames.USERS_RESET_PASSWORD);
            statement.setString(1, password);
            statement.setInt(2, userId);

            if(statement.executeUpdate() == 1)
                result = new DatabaseManipulationResult(true);
            else
                result = new DatabaseManipulationResult(false, Constants.SQL_ERROR_NOT_UPDATED);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            result = new DatabaseManipulationResult(false, e);
        }
        finally
        {
            return result;
        }
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc="Resources management methods">
    /**
     * Retrieves the virtual resources that matches the resource and server ids.
     *
     * @param resourceId the id of the resource
     * @param serverId the id of the server on which the resource resides
     * @param resourceType the type of the resource
     * @return the resource data if available or <code>null</code> otherwise
     *
     * @see Constants Resource Types
     */
    public VirtualResourceBean getVirtualResource(String resourceId, int serverId, VirtualResourceType resourceType)
    {
        VirtualResourceBean resource = null;
        int dbResourceType = Constants.DB_RESOURCE_INVALID;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        //determines in which table to search for the resource based on its type
        switch(resourceType)
        {
            case MACHINE: dbResourceType = Constants.DB_RESOURCE_VIRTUAL_MACHINE; break;
            case MEDIUM: dbResourceType = Constants.DB_RESOURCE_VIRTUAL_MEDIUM; break;
            case NETWORK: dbResourceType = Constants.DB_RESOURCE_VIRTUAL_NETWORK; break;
            default: return resource;
        }

        try
        {
            //builds the sql query, executes it and retrieves the result
            PreparedStatement statement = preparedStatements.get(StatementNames.RESOURCES_GET_BY_ID);
            statement.setString(1, resourceId);
            statement.setInt(2, serverId);
            statement.setInt(3, dbResourceType);
            ResultSet result = statement.executeQuery();
            if(result.next())
            {
                resource = new VirtualResourceBean(result.getString(V_RESOURCES_RESOURCE_ID),
                                                   result.getInt(V_RESOURCES_SERVER_ID),
                                                   result.getInt(V_RESOURCES_OWNER_ID),
                                                   result.getTimestamp(V_RESOURCES_DATE_CREATED),
                                                   result.getString(V_RESOURCES_PERMISSIONS),
                                                   result.getInt(V_RESOURCES_RESOURCE_TYPE));
            }
            else
                resource = null;
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            resource = null;
        }
        finally
        {
            return resource;
        }
    }

    /**
     * Retrieves all virtual resources of the specified type on the specified server.
     *
     * @param serverId the id of the server
     * @param resourceType the type of the resource(s)
     * @return a list of the available resources
     *
     * @see Constants Resource Types
     */
    public ArrayList<VirtualResourceBean> getVirtualResourcesByServer(int serverId, VirtualResourceType resourceType)
    {
        ArrayList<VirtualResourceBean> resources = new ArrayList<VirtualResourceBean>();
        int dbResourceType = Constants.DB_RESOURCE_INVALID;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        //determines in which table to search for the resource based on its type
        switch(resourceType)
        {
            case MACHINE: dbResourceType = Constants.DB_RESOURCE_VIRTUAL_MACHINE; break;
            case MEDIUM: dbResourceType = Constants.DB_RESOURCE_VIRTUAL_MEDIUM; break;
            case NETWORK: dbResourceType = Constants.DB_RESOURCE_VIRTUAL_NETWORK; break;
            default: return resources;
        }

        try
        {
            //builds the sql query, executes it and retrieves the result
            PreparedStatement statement = preparedStatements.get(StatementNames.RESOURCES_GET_ALL_BY_SERVER);
            statement.setInt(1, serverId);
            statement.setInt(2, dbResourceType);
            ResultSet result = statement.executeQuery();
            fillVirtualResourcesList(result, resources);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
        }
        finally
        {
            return resources;
        }
    }

    /**
     * Retrieves all resources of the specified type, owned by the user with the
     * specified id.
     *
     * @param ownerId the id of the resources owner
     * @param resourceType the type of the resource(s)
     * @return a list of all available resources
     *
     * @see Constants Resource Types
     */
    public ArrayList<VirtualResourceBean> getVirtualResourcesByOwner(int ownerId, VirtualResourceType resourceType)
    {
        ArrayList<VirtualResourceBean> resources = new ArrayList<VirtualResourceBean>();
        int dbResourceType = Constants.DB_RESOURCE_INVALID;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        //determines in which table to search for the resource based on its type
        switch(resourceType)
        {
            case MACHINE: dbResourceType = Constants.DB_RESOURCE_VIRTUAL_MACHINE; break;
            case MEDIUM: dbResourceType = Constants.DB_RESOURCE_VIRTUAL_MEDIUM; break;
            case NETWORK: dbResourceType = Constants.DB_RESOURCE_VIRTUAL_NETWORK; break;
            default: return resources;
        }

        try
        {
            //builds the sql query, executes it and retrieves the result
            PreparedStatement statement = preparedStatements.get(StatementNames.RESOURCES_GET_ALL_BY_OWNER);
            statement.setInt(1, ownerId);
            statement.setInt(2, dbResourceType);

            ResultSet result = statement.executeQuery();
            fillVirtualResourcesList(result, resources);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
        }
        finally
        {
            return resources;
        }
    }

    /**
     * Retrieves all virtual resources of the specified type.
     *
     * @param resourceType the type of the resource(s)
     * @return a list of all available resources
     *
     * @see Constants Resource Types
     */
    public ArrayList<VirtualResourceBean> getVirtualResources(VirtualResourceType resourceType)
    {
        ArrayList<VirtualResourceBean> resources = new ArrayList<VirtualResourceBean>();
        int dbResourceType = Constants.DB_RESOURCE_INVALID;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        //determines in which table to search for the resource based on its type
        switch(resourceType)
        {
            case MACHINE: dbResourceType = Constants.DB_RESOURCE_VIRTUAL_MACHINE; break;
            case MEDIUM: dbResourceType = Constants.DB_RESOURCE_VIRTUAL_MEDIUM; break;
            case NETWORK: dbResourceType = Constants.DB_RESOURCE_VIRTUAL_NETWORK; break;
            default: return resources;
        }

        try
        {
            //builds the sql query, executes it and retrieves the result
            PreparedStatement statement = preparedStatements.get(StatementNames.RESOURCES_GET_ALL);
            statement.setInt(1, dbResourceType);

            ResultSet result = statement.executeQuery();
            fillVirtualResourcesList(result, resources);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
        }
        finally
        {
            return resources;
        }
    }

    /**
     * Retrieves the number of virtual resources of the specified type that the
     * user has.
     *
     * @param userId the ID of the user to be checked
     * @param resourceType the type of resources to be checked
     * @return the number of virtual resources
     */
    public int getNumberOfVirtualResourcesForUser(int userId, VirtualResourceType resourceType)
    {
        int number = 0;
        int dbResourceType = Constants.DB_RESOURCE_INVALID;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        //determines in which table to search for the resource based on its type
        switch(resourceType)
        {
            case MACHINE: dbResourceType = Constants.DB_RESOURCE_VIRTUAL_MACHINE; break;
            case MEDIUM: dbResourceType = Constants.DB_RESOURCE_VIRTUAL_MEDIUM; break;
            case NETWORK: dbResourceType = Constants.DB_RESOURCE_VIRTUAL_NETWORK; break;
            default: return number;
        }

        try
        {
            //retrieves, sets up and executes the prepared statement; retrieves and builds the result
            PreparedStatement statement = preparedStatements.get(StatementNames.RESOURCES_GET_NUMBER_FOR_USER);
            statement.setInt(1, userId);
            statement.setInt(2,  dbResourceType);
            ResultSet result = statement.executeQuery();
            if(result.next())
                number = result.getInt(TABLE_TEMP_COUNT_COLUMN);
            else
                number = 0;
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
        }
        finally
        {
            return number;
        }
    }

    /**
     * Creates a new virtual resource of the specified type based on the supplied data.
     *
     * @param resource resource data
     * @return an object containing the result of the requested operation
     *
     * @see DatabaseManipulationResult Return Info
     * @see Constants Possible SQL Error Codes
     * @see Constants Resource Types
     */
    public DatabaseManipulationResult insertVirtualResource(VirtualResourceBean resource)
    {
        DatabaseManipulationResult result = null;
        int dbResourceType = Constants.DB_RESOURCE_INVALID;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        //determines in which table to search for the resource based on its type
        switch(resource.getResourceType())
        {
            case MACHINE: dbResourceType = Constants.DB_RESOURCE_VIRTUAL_MACHINE; break;
            case MEDIUM: dbResourceType = Constants.DB_RESOURCE_VIRTUAL_MEDIUM; break;
            case NETWORK: dbResourceType = Constants.DB_RESOURCE_VIRTUAL_NETWORK; break;
            default: return result;
        }

        try
        {
            //builds the sql query and executes it
            PreparedStatement statement = preparedStatements.get(StatementNames.RESOURCES_INSERT);
            statement.setString(1, resource.getResourceId());
            statement.setInt(2, resource.getServerId());
            statement.setInt(3, resource.getOwnerId());
            statement.setString(4, resource.getPermissions());
            statement.setInt(5, dbResourceType);
            
            statement.executeUpdate();
            result = new DatabaseManipulationResult(true);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            result = new DatabaseManipulationResult(false, e);
        }
        finally
        {
            return result;
        }
    }

    /**
     * Removes a resource from the database.
     *
     * @param resourceId the id of the resource to be removed
     * @param serverId the server on which the resource resides
     * @return an object containing the result of the requested operation
     *
     * @see DatabaseManipulationResult Return Info
     * @see Constants Possible SQL Error Codes
     * @see Constants Resource Types
     */
    public DatabaseManipulationResult removeVirtualResource(String resourceId, int serverId)
    {
        DatabaseManipulationResult result = null;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //builds the sql query and executes it
            PreparedStatement statement = preparedStatements.get(StatementNames.RESOURCES_REMOVE);
            statement.setString(1, resourceId);
            statement.setInt(2, serverId);
           
            if(statement.executeUpdate() == 1)
                result = new DatabaseManipulationResult(true);
            else
                result = new DatabaseManipulationResult(false, Constants.SQL_ERROR_NOT_REMOVED);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            result = new DatabaseManipulationResult(false, e);
        }
        finally
        {
            return result;
        }
    }

    /**
     * Changes the owner of the specified resource.
     *
     * @param resourceId the id of the resource
     * @param serverId the id of the server on which the resource resides
     * @param ownerId the id of the new owner
     * @return an object containing the result of the requested operation
     *
     * @see DatabaseManipulationResult Return Info
     * @see Constants Possible SQL Error Codes
     * @see Constants Resource Types
     */
    public DatabaseManipulationResult changeVirtualResourceOwner(String resourceId, int serverId, int ownerId)
    {
        DatabaseManipulationResult result = null;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //builds the sql query and executes it
            PreparedStatement statement = preparedStatements.get(StatementNames.RESOURCES_UPDATE_OWNER);
            statement.setInt(1, ownerId);
            statement.setString(2, resourceId);
            statement.setInt(3, serverId);
            
            if(statement.executeUpdate() == 1)
                result = new DatabaseManipulationResult(true);
            else
                result = new DatabaseManipulationResult(false, Constants.SQL_ERROR_NOT_UPDATED);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            result = new DatabaseManipulationResult(false, e);
        }
        finally
        {
            return result;
        }
    }

    /**
     * Updates the permissions associated with the specified resource.
     *
     * @param resourceId the id of the resource
     * @param serverId the id of the server on which the resource resides
     * @param permissions the new permissions for the resource
     * @return an object containing the result of the requested operation
     *
     * @see DatabaseManipulationResult Return Info
     * @see Constants Possible SQL Error Codes
     * @see Constants Resource Types
     */
    public DatabaseManipulationResult updateVirtualResourcePermissions(String resourceId, int serverId, String permissions)
    {
        DatabaseManipulationResult result = null;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //builds the sql query and executes it
            PreparedStatement statement = preparedStatements.get(StatementNames.RESOURCES_UPDATE_PERMISSIONS);
            statement.setString(1, permissions);
            statement.setString(2, resourceId);
            statement.setInt(3, serverId);
            
            if(statement.executeUpdate() == 1)
                result =  new DatabaseManipulationResult(true);
            else
                result = new DatabaseManipulationResult(false, Constants.SQL_ERROR_NOT_UPDATED);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            result = new DatabaseManipulationResult(false, e);
        }
        finally
        {
            return result;
        }
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc="Internal networks management methods">
    /**
     * Retrieves an internal network based on the supplied network and server ids.
     *
     * @param networkId the id of the network to be retrieved
     * @param serverId the id of the server on which the network resides
     * @return the network data if available or <code>null</code> otherwise
     */
    public InternalNetworkBean getInternalNetwork(String networkId, int serverId)
    {
        InternalNetworkBean network = null;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //builds the sql query, executes it and retrieves the result
            PreparedStatement statement = preparedStatements.get(StatementNames.INTERNAL_NET_GET_BY_ID);
            statement.setString(1, networkId);
            statement.setInt(2, serverId);
            ResultSet result = statement.executeQuery();
            if(result.next())
            {
                network = new InternalNetworkBean(result.getString(INTERNAL_NETWORKS_NETWORK_ID),
                                                  result.getInt(INTERNAL_NETWORKS_SERVER_ID),
                                                  result.getString(INTERNAL_NETWORKS_EXTERNAL_NAME),
                                                  result.getBoolean(INTERNAL_NETWORKS_DHCP_AVAILABLE),
                                                  result.getInt(INTERNAL_NETWORKS_NUMBER_OF_ATTACHED_NICS));
            }
            else
                network = null;
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            network = null;
        }
        finally
        {
            return network;
        }
    }

    /**
     * Retrieves all internal networks.
     *
     * @return a list of all available internal networks
     */
    public ArrayList<InternalNetworkBean> getInternalNetworks()
    {
        ArrayList<InternalNetworkBean> networks = new ArrayList<InternalNetworkBean>();

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //builds the sql query, executes it and retrieves the result
            PreparedStatement statement = preparedStatements.get(StatementNames.INTERNAL_NET_GET_ALL);
            ResultSet result = statement.executeQuery();
            fillInternalNetworksList(result, networks);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
        }
        finally
        {
            return networks;
        }
    }

    /**
     * Retrieves all internal networks on the specified server.
     *
     * @param serverId the server on which the networks reside
     * @return a list of all available internal networks on the specified server
     */
    public ArrayList<InternalNetworkBean> getInternalNetworksByServer(int serverId)
    {
        ArrayList<InternalNetworkBean> resources = new ArrayList<InternalNetworkBean>();

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //builds the sql query, executes it and retrieves the result
            PreparedStatement statement = preparedStatements.get(StatementNames.INTERNAL_NET_GET_ALL_BY_SERVER);
            statement.setInt(1, serverId);
            ResultSet result = statement.executeQuery();
            fillInternalNetworksList(result, resources);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
        }
        finally
        {
            return resources;
        }
    }

    /**
     * Inserts a new internal networks in the database.
     *
     * @param network the data for the new network
     * @return an object containing the result of the requested operation
     */
    public DatabaseManipulationResult insertInternalNetwork(InternalNetworkBean network)
    {
        DatabaseManipulationResult result = null;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //builds the sql query and executes it
            PreparedStatement statement = preparedStatements.get(StatementNames.INTERNAL_NET_INSERT);
            statement.setString(1, network.getNetworkId());
            statement.setInt(2, network.getServerId());
            statement.setString(3, network.getNetworkName());

            statement.executeUpdate();
            result = new DatabaseManipulationResult(true);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            result = new DatabaseManipulationResult(false, e);
        }
        finally
        {
            return result;
        }
    }

    /**
     * Removes an internal network from the database.
     *
     * @param networkId the id of the network to be removed
     * @param serverId the id of the server on which the network resides
     * @return an object containing the result of the requested operation
     */
    public DatabaseManipulationResult removeInternalNetwork(String networkId, int serverId)
    {
        DatabaseManipulationResult result = null;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //builds the sql query and executes it
            PreparedStatement statement = preparedStatements.get(StatementNames.INTERNAL_NET_REMOVE);
            statement.setString(1, networkId);
            statement.setInt(2, serverId);

            if(statement.executeUpdate() == 1)
                result = new DatabaseManipulationResult(true);
            else
                result = new DatabaseManipulationResult(false, Constants.SQL_ERROR_NOT_REMOVED);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            result = new DatabaseManipulationResult(false, e);
        }
        finally
        {
            return result;
        }
    }

    /**
     * Updates the external name of the specified internal network.
     *
     * @param networkId the id of the internal network
     * @param serverId the id of the server on which the network resides
     * @param newNetworkName the new external name of the network
     * @return an object containing the result of the requested operation
     */
    public DatabaseManipulationResult changeInternalNetworkName(String networkId, int serverId, String newNetworkName)
    {
        DatabaseManipulationResult result = null;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //builds the sql query and executes it
            PreparedStatement statement = preparedStatements.get(StatementNames.INTERNAL_NET_CHANGE_NAME);
            statement.setString(1, newNetworkName);
            statement.setString(2, networkId);
            statement.setInt(3, serverId);
            
            if(statement.executeUpdate() == 1)
                result = new DatabaseManipulationResult(true);
            else
                result = new DatabaseManipulationResult(false, Constants.SQL_ERROR_NOT_UPDATED);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            result = new DatabaseManipulationResult(false, e);
        }
        finally
        {
            return result;
        }
    }

    /**
     * Updates the DHCP server availability for the specified internal network.
     *
     * @param networkId the id of the network
     * @param serverId the id of the server on which the network resides
     * @param dhcpAvailability the DHCP server availability (<code>true</code> -> available
     *        <code>false</code> -> not available)
     * @return an object containing the result of the requested action
     */
    public DatabaseManipulationResult changeInternalNetworkDHCPAvailability(String networkId, int serverId, boolean dhcpAvailability)
    {
        DatabaseManipulationResult result = null;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //builds the sql query and executes it
            PreparedStatement statement = preparedStatements.get(StatementNames.INTERNAL_NET_UPDATE_DHCP_AVAIL);
            statement.setBoolean(1, dhcpAvailability);
            statement.setString(2, networkId);
            statement.setInt(3, serverId);

            if(statement.executeUpdate() == 1)
                result = new DatabaseManipulationResult(true);
            else
                result = new DatabaseManipulationResult(false, Constants.SQL_ERROR_NOT_UPDATED);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            result = new DatabaseManipulationResult(false, e);
        }
        finally
        {
            return result;
        }
    }

    /**
     * Increases the number of NICs that are attached to the specified internal network on
     * the specified server.
     *
     * @param networkId the id of the internal network
     * @param serverId the id of the server on which the network resides
     * @return an object containing the result of the requested action
     */
    public DatabaseManipulationResult increaseNumberOfInternalNetworkAttachedNICs(String networkId, int serverId)
    {
        DatabaseManipulationResult result = null;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        //retrieves the number of NICs currently attached to the internal network
        int currentNumberOfNICs = getNumberOfInternalNetworkAttachedNICs(networkId, serverId);

        try
        {
            if(currentNumberOfNICs > Utilities.Constants.INVALID_NIC_NUMBER) //checks if a valid NIC number was retrieved
            {
                currentNumberOfNICs++; //increases the number of NICs

                //builds the sql query and executes it
                PreparedStatement statement = preparedStatements.get(StatementNames.INTERNAL_NET_UPDATE_NICS);
                statement.setInt(1, currentNumberOfNICs);
                statement.setString(2, networkId);
                statement.setInt(3, serverId);

                if(statement.executeUpdate() == 1)
                    result = new DatabaseManipulationResult(true);
                else
                    result = new DatabaseManipulationResult(false, Constants.SQL_ERROR_NOT_UPDATED);
            }
            else
                result = new DatabaseManipulationResult(false, Constants.SQL_ERROR_NOT_UPDATED);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            result = new DatabaseManipulationResult(false, e);
        }
        finally
        {
            return result;
        }
    }

    /**
     * Decreases the number of NICs that are attached to the specified internal network on
     * the specified server. <br><br>
     *
     * <b>Note:</b> <i>If the number of attached NICs is already 0 the operation will fail.</i>
     *
     * @param networkId the id of the internal network
     * @param serverId the id of the server on which the network resides
     * @return an object containing the result of the requested action
     */
    public DatabaseManipulationResult decreaseNumberOfInternalNetworkAttachedNICs(String networkId, int serverId)
    {
        DatabaseManipulationResult result = null;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        //retrieves the number of NICs currently attached to the internal network
        int currentNumberOfNICs = getNumberOfInternalNetworkAttachedNICs(networkId, serverId);

        try
        {
            if(currentNumberOfNICs > 0) //checks if the number of NICs can be decreased
            {
                currentNumberOfNICs--; //decreases the number of NICs

                //builds the sql query and executes it
                PreparedStatement statement = preparedStatements.get(StatementNames.INTERNAL_NET_UPDATE_NICS);
                statement.setInt(1, currentNumberOfNICs);
                statement.setString(2, networkId);
                statement.setInt(3, serverId);

                if(statement.executeUpdate() == 1)
                    result = new DatabaseManipulationResult(true);
                else
                    result = new DatabaseManipulationResult(false, Constants.SQL_ERROR_NOT_UPDATED);
            }
            else
                result = new DatabaseManipulationResult(false, Constants.SQL_ERROR_NOT_UPDATED);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            result = new DatabaseManipulationResult(false, e);
        }
        finally
        {
            return result;
        }
    }

    /**
     * Retrieves the number of NICs currently attached to the specified internal
     * network on the specified server.
     *
     * @param networkId the id of the internal network
     * @param serverId the id of the server on which the network resides
     * @return the number of NICs currently attached to network or an error code
     *         if the operation fails
     *
     * @see Utilities.Constants#INVALID_NIC_NUMBER Error Code
     */
    public int getNumberOfInternalNetworkAttachedNICs(String networkId, int serverId)
    {
        int result = Utilities.Constants.INVALID_NIC_NUMBER;

        if(connectionVerificationEnabled)
            verifyConnection(); //makes sure the conneciton is valid
        else
            ;

        try
        {
            //builds the sql query and executes it
            PreparedStatement statement = preparedStatements.get(StatementNames.INTERNAL_NET_GET_NICS);
            statement.setString(1, networkId);
            statement.setInt(2, serverId);

            ResultSet resultData = statement.executeQuery();
            resultData.next();
            result = resultData.getInt(INTERNAL_NETWORKS_NUMBER_OF_ATTACHED_NICS);
        }
        catch(SQLException e)
        {
            logsManager.logSystemEvent(System.currentTimeMillis(), Constants.LOG_SEVERITY_DEBUG, e.getMessage());
            result = Utilities.Constants.INVALID_NIC_NUMBER;
        }
        finally
        {
            return result;
        }
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc="ArrayList building methods">
    //pre -> initialized array list (could be non-empty)
    //post -> new data is appended to the list
    /**
     * Builds a list of logs using the supplied SQL query result
     *
     * @param queryResult the result of a SQL query
     * @param logsArrayList the list that is to be filled
     * @throws SQLException
     *
     * @see ResultSet#next() Exception Info
     */
    private void fillLogsList(ResultSet queryResult, ArrayList<LogBean> logsArrayList) throws SQLException
    {
        queryResult.beforeFirst(); //resets the result pointer
        while(queryResult.next())  //goes through each available result
        {
            //builds and adds the data object to the list
            logsArrayList.add(new LogBean(queryResult.getInt(LOGS_USER_ID),
                                          queryResult.getInt(LOGS_SERVER_ID),
                                          queryResult.getInt(LOGS_EVENT_ID),
                                          queryResult.getString(LOGS_SEVERITY),
                                          queryResult.getTimestamp(LOGS_EVENT_DATE),
                                          queryResult.getString(LOGS_DESCRIPTION)));
        }
    }

    //pre -> initialized array list (could be non-empty)
    //post -> new data is appended to the list
    /**
     * Builds a list of permissions using the supplied SQL query result
     *
     * @param queryResult the result of a SQL query
     * @param permissionsArrayList  the list that is to be filled
     * @throws SQLException
     *
     * @see ResultSet#next() Exception Info
     */
    private void fillPermissionsList(ResultSet queryResult, ArrayList<PermissionsBean> permissionsArrayList) throws SQLException
    {
        queryResult.beforeFirst(); //resets the result pointer
        while(queryResult.next()) //goes through each available result
        {
            //builds and adds the data object to the list
            permissionsArrayList.add(new PermissionsBean(queryResult.getInt(PERMISSIONS_USER_ID),
                                                         queryResult.getInt(PERMISSIONS_SERVER_ID),
                                                         queryResult.getString(PERMISSIONS_MACHINES_PERM),
                                                         queryResult.getString(PERMISSIONS_MEDIA_PERM),
                                                         queryResult.getString(PERMISSIONS_NETWORKS_PERM)));
        }
    }

    //pre -> initialized array list
    //post -> data is appended to the list, no username or password is set for serverbean
    /**
     * Builds a list of servers using the supplied SQL query result
     *
     * @param queryResult the result of a SQL query
     * @param serversArrayList the list that is to be filled
     * @throws SQLException
     *
     * @see ResultSet#next() Exception Info
     */
    private void fillServersList(ResultSet queryResult, ArrayList<ServerBean> serversArrayList) throws SQLException
    {
        queryResult.beforeFirst(); //resets the result pointer
        while(queryResult.next()) //goes through each available result
        {
            //builds and adds the data object to the list
            serversArrayList.add(new ServerBean(queryResult.getInt(SERVERS_SERVER_ID),
                                                queryResult.getTimestamp(SERVERS_DATE_ADDED),
                                                queryResult.getString(SERVERS_NAME),
                                                queryResult.getString(SERVERS_DESCRIPTION),
                                                queryResult.getString(SERVERS_ADDRESS),
                                                null,
                                                null,
                                                queryResult.getString(SERVERS_SF_ROOT),
                                                queryResult.getInt(SERVERS_VRDP_PORTS_LOW),
                                                queryResult.getInt(SERVERS_VRDP_PORTS_HIGH),
                                                queryResult.getInt(SERVERS_VRDP_PORT_PER_VM),
                                                queryResult.getString(SERVERS_VRDP_ALLOCATED_SLOTS)));
        }
    }

    //pre -> initialized array list
    //post -> data is appended to the list, no password is set for the user bean
    /**
     * Builds a list of users using the supplied SQL query result
     *
     * @param queryResult the result of a SQL query
     * @param usersArrayList the list that is to be filled
     * @throws SQLException
     *
     * @see ResultSet#next() Exception Info
     */
    private void fillUsersList(ResultSet queryResult, ArrayList<UserBean> usersArrayList) throws SQLException
    {
        queryResult.beforeFirst(); //resets the result pointer
        while(queryResult.next()) //goes through each available result
        {
            //builds and adds the data object to the list
            usersArrayList.add(new UserBean(queryResult.getInt(USERS_ID),
                                            queryResult.getString(USERS_NAME),
                                            queryResult.getTimestamp(USERS_DATE_CREATED),
                                            queryResult.getTimestamp(USERS_DATE_LAST_LOGIN),
                                            queryResult.getInt(USERS_ACCOUNT_LEVEL),
                                            queryResult.getString(USERS_LAST_lOGIN_IP)));
        }
    }

    //pre -> initialized array list
    //post -> data is appended to the list, no password is set for the user bean
    /**
     * Builds a list of resources using the supplied SQL query result
     *
     * @param queryResult the result of a SQL query
     * @param resourcesList the list that is to be filled
     * @throws SQLException
     *
     * @see ResultSet#next() Exception Info
     */
    private void fillVirtualResourcesList(ResultSet queryResult, ArrayList<VirtualResourceBean> resourcesList) throws SQLException
    {
        queryResult.beforeFirst(); //resets the result pointer
        while(queryResult.next())  //goes through each available result
        {
            //builds and adds the data object to the list
            resourcesList.add(new VirtualResourceBean(queryResult.getString(V_RESOURCES_RESOURCE_ID),
                                                      queryResult.getInt(V_RESOURCES_SERVER_ID),
                                                      queryResult.getInt(V_RESOURCES_OWNER_ID),
                                                      queryResult.getTimestamp(V_RESOURCES_DATE_CREATED),
                                                      queryResult.getString(V_RESOURCES_PERMISSIONS),
                                                      queryResult.getInt(V_RESOURCES_RESOURCE_TYPE)));
        }
    }

    //pre -> initialized array list
    //post -> data is appended to the list
    /**
     * Builds a list of resources using the supplied SQL query result
     *
     * @param queryResult the result of a SQL query
     * @param resourcesList the list that is to be filled
     * @throws SQLException
     *
     * @see ResultSet#next() Exception Info
     */
    private void fillInternalNetworksList(ResultSet queryResult, ArrayList<InternalNetworkBean> resourcesList) throws SQLException
    {
        queryResult.beforeFirst(); //resets the result pointer
        while(queryResult.next())  //goes through each available result
        {
            //builds and adds the data object to the list
            resourcesList.add(new InternalNetworkBean(queryResult.getString(INTERNAL_NETWORKS_NETWORK_ID),
                                                      queryResult.getInt(INTERNAL_NETWORKS_SERVER_ID),
                                                      queryResult.getString(INTERNAL_NETWORKS_EXTERNAL_NAME),
                                                      queryResult.getBoolean(INTERNAL_NETWORKS_DHCP_AVAILABLE),
                                                      queryResult.getInt(INTERNAL_NETWORKS_NUMBER_OF_ATTACHED_NICS)));
        }
    }
    //</editor-fold>
}
